<?php
/**
 * 实例化开放平台的 youzan App
 * Author: hezhizheng
 *
 * @link https://github.com/Hanson/youzan-sdk
 */

namespace App\Services\Youzan;

use App\Exceptions\ApiErrCode;
use App\Exceptions\ApiException;
use App\Http\Controllers\Youzan\OAuthController;
use App\Models\Youzan\YouzanAuthorizer;

class AppFactory
{

    // 有赞 api

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_shop/shop/youzan.shop.get
     */
    const  YOUZAN_SHOP_GET = 'youzan.shop.get'; // 获取店铺基础信息

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_shop/shop/youzan.shop.basic.get
     */
    const  YOUZAN_SHOP_BASIC_GET = 'youzan.shop.basic.get'; // 获取店铺基本信息

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_item/item/youzan.items.onsale.get
     */
    const  YOUZAN_ITEMS_ONSALE_GET = 'youzan.items.onsale.get'; // 获取出售中的商品列表

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_item/item/youzan.items.inventory.get
     */
    const  YOUZAN_ITEMS_INVENTORY_GET = 'youzan.items.inventory.get'; // 获取仓库中的商品列表

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_buyer/buyer_bill/youzan.trade.bill.good.url.get
     */
    const  YOUZAN_TRADE_BILL_GOOD_URL_GET = 'youzan.trade.bill.good.url.get'; // 下单入口，进入结算页

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_buyer/buyer_bill/youzan.trade.bill.goods.url.get
     */
    const  YOUZAN_TRADE_BILL_GOODS_URL_GET = 'youzan.trade.bill.goods.url.get'; // 多商品下单入口，进入结算页

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_trade/trade/youzan.trades.sold.get
     */
    const  YOUZAN_TRADES_SOLD_GET = 'youzan.trades.sold.get'; // 查询卖家已卖出的交易列表

    /**
     * @link https://www.youzanyun.com/apilist/detail/group_trade/trade/youzan.trade.get
     */
    const  YOUZAN_TRADE_GET = 'youzan.trade.get'; // 获取单笔交易的信息

    /**
     * @var \Hanson\Youzan\Youzan
     */
    public $youzan;

    protected $author_youzan_cache = [
        'author_id' => 'author_youzan'
    ];

    /**
     * AppFactory constructor.
     *
     */
    public function __construct()
    {
        /**
         * @link https://github.com/Hanson/youzan-sdk - 工具型应用配置
         */
        $this->youzan = new \Hanson\Youzan\Youzan([
            'client_id'     => config('pkx.youzan.client_id'),
            'client_secret' => config('pkx.youzan.client_secret'),
            'debug'         => config('app.debug'),
            'redirect_uri'  => route(OAuthController::PRE_AUTH_CALLBACK_ROUTE),
            'log'           => [
                'name'       => 'youzan',
                'file'       => storage_path('/logs/youzan.log'),
                'level'      => config('app.debug') ? 'debug' : 'error',
                'permission' => 0777,
            ]
        ]);
    }

    /**
     * @return \Hanson\Youzan\Youzan
     */
    public static function youzan()
    {
        return (new self)->youzan;
    }


    /**
     * @param YouzanAuthorizer $author
     * @return string
     * @throws \Throwable
     */
    public static function getAccessToken(YouzanAuthorizer $author)
    {
        if ($author->tokenExpired()) {
            $self = new self;

            $token_res = $self->youzan->pre_auth->refreshToken($author->refresh_token);
                $self->checkHasError($token_res);

            $author->updateToken($token_res);
        }

        return $author->access_token;
    }

    /**
     * @param array $token_res
     * @return bool
     * @throws ApiException
     * @throws \App\Exceptions\ApiSilentException
     */
    private static function checkHasError(array $token_res): bool
    {
        if (isset($token_res['error'])) {
            throw new ApiException(
                ApiErrCode::YOUZAN_ERROR,
                $token_res['error_description'] . '，请重新授权'
            );
        }
        return true;
    }


    /**
     * @param YouzanAuthorizer $youzanAuthorizer
     *
     * @return mixed
     * @throws \Throwable
     */
    public function getAuthorYouzan(YouzanAuthorizer $youzanAuthorizer)
    {
        $id = $youzanAuthorizer->getKey();

        if (! isset($this->author_youzan_cache[$id])) {
            $token = $this->getAccessToken($youzanAuthorizer);
            $author_youzan = $this->youzan->oauth->createAuthorization($token);

            $this->author_youzan_cache[$id] = $author_youzan;
        }

        return $this->author_youzan_cache[$id];
    }
}